﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ComponentModel.DataAnnotations;

namespace DarkLight.Model
{
    [DataContract]
    public class Rotation : ObservableObject
    {
        #region Constructors
        public Rotation()
            : this(0,0,0)
        {
        }

        public Rotation(float rx, float ry, float rz)
        {
            this.RX = rx;
            this.RY = ry;
            this.RZ = rz;
        }
        #endregion

        #region Static Members
        public static Rotation Zero
        {
            get 
            {
                return new Rotation(0.0f, 0.0f, 0.0f);
            }
        }
        #endregion

        #region Public Members
        [DataMember]
        [Range(0, 2.0 * Math.PI)]
        public float RX
        {
            get { return _RX; }
            set
            {
                if (_RX != value)
                {
                    _RX = value;
                    RaisePropertyChanged("RX");
                }
            }
        }
        private float _RX;

        [DataMember]
        [Range(0, 2.0 * Math.PI)]
        public float RY
        {
            get { return _RY; }
            set
            {
                if (_RY != value)
                {
                    _RY = value;
                    RaisePropertyChanged("RY");
                }
            }
        }
        private float _RY;

        [DataMember]
        [Range(0, 2.0 * Math.PI)]
        public float RZ
        {
            get { return _RZ; }
            set
            {
                if (_RZ != value)
                {
                    _RZ = value;
                    RaisePropertyChanged("RZ");
                }
            }
        }
        private float _RZ;
        #endregion

        #region Operators Overloads
        public override bool Equals(object obj)
        {
            var sObj = obj as Rotation;
            return this == sObj;
        }

        public static bool operator ==(Rotation rotationCS, Rotation rotationCS2)
        {
            if (object.ReferenceEquals(rotationCS, null) && object.ReferenceEquals(rotationCS2, null))
                return true;
            else if (object.ReferenceEquals(rotationCS, null))
                return false;
            else if (object.ReferenceEquals(rotationCS2, null))
                return false;
            return rotationCS.RX == rotationCS2.RX && rotationCS.RY == rotationCS2.RY && rotationCS.RZ == rotationCS2.RZ;
        }

        public static bool operator !=(Rotation rotationCS, Rotation rotationCS2)
        {
            if (object.ReferenceEquals(rotationCS, null) && object.ReferenceEquals(rotationCS2, null))
                return false;
            else if (object.ReferenceEquals(rotationCS, null))
                return true;
            else if (object.ReferenceEquals(rotationCS2, null))
                return true;
            return !(rotationCS.RX == rotationCS2.RX && rotationCS.RY == rotationCS2.RY && rotationCS.RZ == rotationCS2.RZ);
        }

        public static Rotation Subtract(Rotation rotationCS, Rotation rotationCS2)
        {
            return rotationCS - rotationCS2;
        }

        public static Rotation operator -(Rotation rotationCS, Rotation rotationCS2)
        {
            if (object.ReferenceEquals(rotationCS, null))
                throw new ArgumentNullException("rotationCS");
            if (object.ReferenceEquals(rotationCS2, null))
                throw new ArgumentNullException("rotationCS2");
            else
                return new Rotation(rotationCS.RX - rotationCS2.RX, rotationCS.RY - rotationCS2.RY, rotationCS.RZ - rotationCS2.RZ);
        }

        public override int GetHashCode()
        {
            return (int)(RX + RY + RZ);
        }
        #endregion
    }
}
